package cn.jlearn.proxy.common.handler;

import cn.jlearn.proxy.common.packet.BsPacket;
import org.tio.core.ChannelContext;
import org.tio.core.TioConfig;
import org.tio.core.exception.TioDecodeException;
import org.tio.core.intf.AioHandler;
import org.tio.core.intf.Packet;

import java.nio.ByteBuffer;

/**
 * @author qianyingchao
 * @version 1.0
 * @date 2021/5/8 5:42 下午
 */
public abstract class AbstractAioHandler implements AioHandler {

    /**
     * 解码：把接收到的ByteBuffer，解码成应用可以识别的业务消息包
     * 消息头：type + bodyLength
     * 消息体：byte[]
     */
    @Override
    public BsPacket decode(ByteBuffer buffer, int limit, int position, int readableLength, ChannelContext channelContext) throws TioDecodeException {
        if (readableLength < BsPacket.HEADER_LENGTH) {
            return null;
        }
        byte type = buffer.get();
        int bodyLength = buffer.getInt();
        if (bodyLength < 0) {
            throw new TioDecodeException("bodyLength [" + bodyLength + "] is not right, remote:" + channelContext.getClientNode());
        }

        int neededLength = BsPacket.HEADER_LENGTH + bodyLength;
        int test = readableLength - neededLength;
        if (test < 0) {
            return null;
        } else {
            BsPacket packet = new BsPacket();
            packet.setType(type);
            if (bodyLength > 0) {
                byte[] dst = new byte[bodyLength];
                buffer.get(dst);
                packet.setBody(dst);
            }
            return packet;
        }
    }

    @Override
    public ByteBuffer encode(Packet p, TioConfig tioConfig, ChannelContext channelContext) {
        BsPacket packet = (BsPacket) p;
        byte[] body = packet.getBody();
        int bodyLen = 0;
        if (body != null) {
            bodyLen = body.length;
        }
        int allLen = BsPacket.HEADER_LENGTH + bodyLen;
        ByteBuffer buffer = ByteBuffer.allocate(allLen);
        buffer.order(tioConfig.getByteOrder());
        buffer.put(packet.getType());
        buffer.putInt(bodyLen);
        if (body != null) {
            buffer.put(body);
        }
        return buffer;
    }

}
